package smecta.client.print.util.weight;

import com.fazecast.jSerialComm.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import smecta.client.print.common.constants.ScaleConstant;
import smecta.client.print.controller.ScaleSettingsController;
import smecta.client.print.controller.ScpDataAcqController;
import smecta.client.print.domain.weight.WeightSensorListenerContext;

import java.nio.charset.StandardCharsets;

public class WeightSensorListener implements SerialPortMessageListener, SerialPortMessageListenerWithExceptions {

    private static final Logger log = LoggerFactory.getLogger(WeightSensorListener.class);

    private WeightSensorListenerContext context;

    final int STABLE_THRESHOLD = 50; // 示例：连续50次读数差异小于阈值视为稳定
    double lastWeight = Double.NaN;

    double STABILITY_THRESHOLD = 0.0;
    int stableCount = 0;

    boolean isStableWeightRecorded = false;

    public WeightSensorListener(WeightSensorListenerContext context) {
        this.context = context;
    }

    @Override
    public byte[] getMessageDelimiter() {
        return new byte[0];
    }

    @Override
    public boolean delimiterIndicatesEndOfMessage() {
        return false;
    }

    @Override
    public int getListeningEvents() {
        return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
    }

    @Override
    public void serialEvent(SerialPortEvent event) {
        if (ScaleConstant.SENSOR_FUNCTION_CODE_001.equals(context.getCode())) {
            function001(event);
            return;
        }
        if (ScaleConstant.SENSOR_FUNCTION_CODE_002.equals(context.getCode())) {
            function002(event);
            return;
        }
        calculateWeightLogic(event);
    }

    private void function001(SerialPortEvent event) {
        if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
            return;
        }

        if (context.getSp().bytesAvailable() <= -1) {
            return;
        }

        byte[] data = new byte[context.getSp().bytesAvailable()];

        context.getSp().readBytes(data, data.length);

        // 将字节数组转换为字符串
        String dataStr = new String(data, StandardCharsets.UTF_8);

        ScaleSettingsController controller = (ScaleSettingsController)context.getBean();

        controller.updateTestArea1(dataStr);

        log.info("scale send data:{}", dataStr);
    }
    private void function002(SerialPortEvent event) {
        if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
            return;
        }

        if (context.getSp().bytesAvailable() <= -1) {
            return;
        }

        byte[] data = new byte[context.getSp().bytesAvailable()];

        context.getSp().readBytes(data, data.length);

        ScpDataAcqController controller = (ScpDataAcqController)context.getBean();
        double currentWeight = parseWeightData(data); // 实现该方法解析接收到的字节数组为体重值
        controller.updateRealtimeWeight(String.valueOf(currentWeight));
        if (!Double.isNaN(lastWeight)) {
            double diff = Math.abs(currentWeight - lastWeight);
            if (diff == STABILITY_THRESHOLD) {
                if (++stableCount == STABLE_THRESHOLD) {
                    print(currentWeight); // 输出稳定后的体重记录
                    context.getExecutor().execute(new Runnable() {
                        @Override
                        public void run() {
                            controller.addBox();
                        }
                    });
                }
            } else {
                stableCount = 0;
            }
        }
        lastWeight = currentWeight;
    }

    private void calculateWeightLogic(SerialPortEvent event) {
        if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
            return;
        }

        if (context.getSp().bytesAvailable() <= -1) {
            return;
        }

        byte[] data = new byte[context.getSp().bytesAvailable()];

        context.getSp().readBytes(data, data.length);

        double currentWeight = parseWeightData(data); // 实现该方法解析接收到的字节数组为体重值
        if (!Double.isNaN(lastWeight)) {
            double diff = Math.abs(currentWeight - lastWeight);
            if (diff == STABILITY_THRESHOLD) {
                if (++stableCount == STABLE_THRESHOLD) {
                    print(currentWeight); // 输出稳定后的体重记录
                }
            } else {
                stableCount = 0;
            }
        }
        lastWeight = currentWeight;
    }

    private double parseWeightData(byte[] data) {
        // 将字节数组转换为字符串
        String dataStr = new String(data, StandardCharsets.UTF_8);
        // 使用正则表达式找到第一个 ST,GS 后跟空格及一个浮点数的模式
        // 注意这里的 "\d+(\.\d+)?" 匹配整数或小数形式的重量值
        String pattern = context.getScaleRegexPattern();
        java.util.regex.Matcher matcher = java.util.regex.Pattern.compile(pattern).matcher(dataStr);

        // 如果找到匹配项,返回对应的重量值,否则返回 NaN
        if (matcher.find()) {
            // group(1) 是第一个括号内的子表达式，即重量值
            log.info("parseWeightData str:{}", matcher.group(1));
            return Double.valueOf(matcher.group(1));
        }
        return Double.NaN;
    }

    private void print(double currentWeight) {
        System.out.println("Stable weight: " + currentWeight); // 输出稳定后的体重记录
    }

    @Override
    public void catchException(Exception e) {
        log.error("WeightSensorListener catchException:{}", e);
    }
}
